package org.jradweb.tools.generator.freemarker;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.maven.plugin.logging.Log;
import org.jradweb.tools.generator.freemarker.util.Templates;
import org.jradweb.tools.generator.utils.StringUtils;

import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Use freemarker template to create class file
 * 
 * @author Paul Wang
 */
public class FreemarkerOperator {
	protected static final java.text.DateFormat DATA_FORMAT = new java.text.SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss.S");

	private File rootPath;

	private Log log;

	private String artifactId;

	private String groupId;

	protected Map<String, Object> map;

	public String getArtifactId() {
		return artifactId;
	}

	public String getGroupId() {
		return groupId;
	}

	public Log getLog() {
		return log;
	}

	public File getRootPath() {
		return rootPath;
	}

	public FreemarkerOperator(File rootPath, Log log, String groupId,
			String artifactId) {
		this.rootPath = rootPath;
		this.log = log;
		this.groupId = groupId;
		this.artifactId = artifactId;

		map = new HashMap<String, Object>();
		map.put("artifactId", this.getArtifactId());
		map.put("groupId", this.getGroupId());

		String nowDate = DATA_FORMAT.format(new Date());
		map.put("createdAt", nowDate);
		map.put("updatedAt", nowDate);

	}

	


	public void createModelFile(String modelName) throws IOException,
			TemplateException {
		File srcPath = this.getSourcePath();

		File packagePath = new File(srcPath.getAbsolutePath() + "/"
				+ StringUtils.packageToPath(getGroupId()) + "/"
				+ getArtifactId() + "/model");

		if (!packagePath.exists()) {
			packagePath.mkdirs();
		}

		File modelFile = new File(packagePath.getAbsoluteFile() + "/"
				+ modelName + ".java");
		if (modelFile.exists()) {
			getLog().info(
					"Model class \"" + modelName + ".java\" already exists!");
			return;
		}
		modelFile.createNewFile();

		this.writeContent(modelFile, Templates.MODEL_TEMPLATE);
		log
				.info("Model class \"" + modelName
						+ ".java\" created successfully!");
	}

	public void createDaoFile(String modelName) throws IOException,
			TemplateException {
		File srcPath = this.getSourcePath();

		File packagePath = new File(srcPath.getAbsolutePath() + "/"
				+ StringUtils.packageToPath(getGroupId()) + "/"
				+ getArtifactId() + "/dao");

		if (!packagePath.exists()) {
			packagePath.mkdirs();
		}

		File daoFile = new File(packagePath.getAbsoluteFile() + "/" + modelName
				+ "Dao.java");
		if (daoFile.exists()) {
			getLog().info(
					"Dao inteface \"" + modelName
							+ "Dao.java\" already exists!");
			return;
		}
		daoFile.createNewFile();

		this.writeContent(daoFile, Templates.DAO_TEMPLATE);
		log.info("Dao inteface \"" + modelName
				+ "Dao.java\" created successfully!");
	}

	public void createDaoImplFile(String modelName) throws IOException,
			TemplateException {
		File srcPath = this.getSourcePath();

		File packagePath = new File(srcPath.getAbsolutePath() + "/"
				+ StringUtils.packageToPath(getGroupId()) + "/"
				+ getArtifactId() + "/dao/impl");

		if (!packagePath.exists()) {
			packagePath.mkdirs();
		}

		File daoFile = new File(packagePath.getAbsoluteFile() + "/" + modelName
				+ "DaoImpl.java");
		if (daoFile.exists()) {
			getLog().info(
					"DaoImpl class \"" + modelName
							+ "DaoImpl.java\" already exists!");
			return;
		}
		daoFile.createNewFile();

		this.writeContent(daoFile, Templates.DAO_IMPL_TEMPLATE);
		log.info("DaoImpl class\"" + modelName
				+ "DaoImpl.java\" created successfully!");
	}

	public void createDaoTestFile(String modelName) throws IOException,
			TemplateException {
		File testPath = this.getTestSourcePath();

		File packagePath = new File(testPath.getAbsolutePath() + "/"
				+ StringUtils.packageToPath(getGroupId()) + "/"
				+ getArtifactId() + "/dao/test");

		if (!packagePath.exists()) {
			packagePath.mkdirs();
		}

		File daoFile = new File(packagePath.getAbsoluteFile() + "/" + modelName
				+ "DaoTest.java");
		if (daoFile.exists()) {
			getLog().info(
					"DaoTest class \"" + modelName
							+ "DaoTest.java\" already exists!");
			return;
		}
		daoFile.createNewFile();

		this.writeContent(daoFile, Templates.DAO_TEST_TEMPLATE);
		log.info("DaoTest class\"" + modelName
				+ "DaoTest.java\" created successfully!");
	}

	public void createDaoTestDataSetFile(String modelName) throws IOException,
			TemplateException {
		File testResourcesPath = this.getTestResourcesPath();

		File packagePath = new File(testResourcesPath.getAbsolutePath() + "/"
				+ StringUtils.packageToPath(getGroupId()) + "/"
				+ getArtifactId() + "/dao/test");

		if (!packagePath.exists()) {
			packagePath.mkdirs();
		}

		File daoFile = new File(packagePath.getAbsoluteFile() + "/" + modelName
				+ "DaoTest.xml");
		if (daoFile.exists()) {
			getLog().info(
					"DaoTest dataset \"" + modelName
							+ "DaoTest.xml\" already exists!");
			return;
		}
		daoFile.createNewFile();

		this.writeContent(daoFile, Templates.DAO_TEST_DATASET_TEMPLATE);
		log.info("DaoTest dataset \"" + modelName
				+ "DaoTest.xml\" created successfully!");
	}

	protected void writeContent(File file, Template template)
			throws IOException, TemplateException {
		java.io.FileWriter writer = new FileWriter(file);
		template.process(map, writer);
		writer.close();
	}

	protected File getSourcePath() {
		File srcPath = new File(getRootPath().getAbsolutePath()
				+ "/src/main/java");
		if (!srcPath.exists()) {
			srcPath.mkdirs();
		}
		return srcPath;
	}

	protected File getPathInSroucePath(String path) {
		File srcPath = this.getSourcePath();
		File packagePath = new File(srcPath.getAbsolutePath() + path);

		if (!packagePath.exists())
			packagePath.mkdirs();

		return packagePath;
	}

	protected File getResourcePath() {
		File rsPath = new File(getRootPath().getAbsolutePath()
				+ "/src/main/resources");
		if (!rsPath.exists()) {
			rsPath.mkdirs();
		}
		return rsPath;
	}

	protected File getPathInResourcePath(String path) {
		File rcPath = this.getResourcePath();
		File packagePath = new File(rcPath.getAbsolutePath() + path);

		if (!packagePath.exists())
			packagePath.mkdirs();

		return packagePath;
	}

	protected File getTestSourcePath() {
		File srcPath = new File(getRootPath().getAbsolutePath()
				+ "/src/test/java");
		if (!srcPath.exists()) {
			srcPath.mkdirs();
		}
		return srcPath;
	}
	
	protected File getPathInTestSourcePath(String path) {
		File tsPath = this.getTestSourcePath();
		File packagePath = new File(tsPath.getAbsolutePath() + path);

		if (!packagePath.exists())
			packagePath.mkdirs();

		return packagePath;
	}

	protected File getTestResourcesPath() {
		File srcPath = new File(getRootPath().getAbsolutePath()
				+ "/src/test/resources");
		if (!srcPath.exists()) {
			srcPath.mkdirs();
		}
		return srcPath;
	}
	
	protected File getPathInTestResourcePath(String path) {
		File trsPath = this.getTestResourcesPath();
		File packagePath = new File(trsPath.getAbsolutePath() + path);

		if (!packagePath.exists())
			packagePath.mkdirs();

		return packagePath;
	}

}
